#include <string>
#include "log.h"
#include "InThread.h"
#include "ProcessThread.h"
#include "OutThread.h"

InThread * pInThread = NULL;
ProcessThread * pProcessThread = NULL;
OutThread * pOutThread = NULL;

void buildMsg(Message * pMsg)
    {
    static int mark = 0;
    mark++;
    char str[256];
    sprintf(str, "%d", mark);
    if (pMsg)
        {
        strcpy((char*) (pMsg->body()), str);
        pMsg->body_length(strlen(str) + 1);
        pMsg->encode_header();
        }
    }

void produceMsgs()
    {
    while (true)
        {
        Message *pMsg = new Message(Message::CT_STRING);
        buildMsg(pMsg);

        if (reinterpret_cast<InThread *> (pInThread)->getInQueue().insertRecord(
                pMsg, false) == true)
            {
            //Let the last dealer to free pMsg.
            LOGCON.infoStream() << __PRETTY_FUNCTION__ << " - OK to insert\n";
            }
        else
            {
            LOGCON.errorStream() << __PRETTY_FUNCTION__
                    << " - Fail to insert\n";
            delete pMsg;
            }
        boost::this_thread::sleep(boost::posix_time::milliseconds(5));
        }

    }

int main()
    {
    try
        {
        boost::asio::io_service io;
        pInThread = new InThread(io);
        pProcessThread = new ProcessThread(io);
        pOutThread = new OutThread(io);

        //class InThread is non-copyable, but boost::thread requires function object
        //copyable, we have to use boost::ref to satisfy.
        boost::thread inThread(boost::ref(*pInThread));
        boost::thread processThread(boost::ref(*pProcessThread));
        boost::thread outThread(boost::ref(*pOutThread));

        boost::thread produceMsgsThread(produceMsgs);

        io.run();
        produceMsgsThread.join();
        inThread.join();
        processThread.join();
        outThread.join();
        }
    catch (std::exception & e)
        {
        LOGCON.errorStream() << "Exception: " << e.what() << "\n";
        }

    return 0;
    }
